package main

import (
	"fmt"
	"sync"
	"sync/atomic"
	"time"
)

// 当我们想要对某个变量在多个goroutine之间进行并发操作时，除了使用官方提供的mutex，还可以使用sync.atomic包
// golang提供的原子操作都是非侵入式的，直接由底层CPU硬件支持
func main() {
	//dStock()
	//dStockWithAtomic()
	compareAndSwap()
	LoadMethod()
	StoreMethod()
	SwapMethod()

}

// dStockWithAtomic
//
//	@Description: 减库存
func dStockWithAtomic() {
	var wg sync.WaitGroup
	var stock int32 = 10000
	for i := 0; i < 10000; i++ {
		wg.Add(1)
		go func() {
			defer wg.Done()
			time.Sleep(time.Millisecond)
			atomic.AddInt32(&stock, -1)
		}()
	}
	wg.Wait()
	fmt.Println("剩余库存=", stock) //剩余库存= 0
}

func dStock() {
	var wg sync.WaitGroup
	var stock int32 = 10000
	for i := 0; i < 10000; i++ {
		wg.Add(1)
		go func() {
			defer wg.Done()
			time.Sleep(time.Millisecond)
			stock--
		}()
	}
	wg.Wait()
	fmt.Println("剩余库存=", stock) //剩余库存= ?
}

// compareAndSwap
//
//	@Description: CAS
func compareAndSwap() {
	var stock int32 = 10000
	swapped := atomic.CompareAndSwapInt32(&stock, 10000, 10001)
	fmt.Println("swapped=", swapped) //swapped= true
	swapped1 := atomic.CompareAndSwapInt32(&stock, 10000, 10001)
	fmt.Println("swapped=", swapped1) //swapped= false
}

// LoadMethod
//
//	@Description: Load
func LoadMethod() {
	var stock int32 = 10000
	val := atomic.LoadInt32(&stock)
	fmt.Println("val=", val)
}

// StoreMethod
//
//	@Description:
func StoreMethod() {
	var stock int32
	atomic.StoreInt32(&stock, 10001)
	fmt.Println("val=", stock)
}

// SwapMethod
//
//	@Description: 将原值替换为指定值，并返回原值
func SwapMethod() {
	var oldStock int32 = 10000
	var newStock int32 = 10001
	rOld := atomic.SwapInt32(&oldStock, newStock)
	fmt.Println("new-val=", newStock) //new-val= 10001
	fmt.Println("old-val=", rOld)     //old-val= 10000
}
